﻿//----------------------------------------------------------------
// Desc: lua 脚本解释器
// Edit: ShowLong, http://blog.csdn.net/showlong
//
// Date Created: 2012-10-26
//
// Update Date : 
//
// Copyright (c) Fuel4D (http://www.fuel4d.com), All rights reserved.
//
//     // ..\\sample\\lua.lua
//     {
//         bool_vl = true
//         int_vl = 10
//         float_vl = 9.52
//         str_vl = "中国人"
//     
//         function add(a, b, str)
//             int_vl = a + b
//             return int_vl, a, b, str
//         end
//     }
//
//     static size_t my_sub_func(IFLuaFuncParameter* args)
//     {
//         // 修改全局变量
//         args->GetLua()->SetInt(_FT("int_vl"), FGetTime());
//     
//         int a, b, is_unicode;
//         // 注意从lua传过来的串只可能是ANSI，如果从代码中传过来的，则允许UINCODE的
//         args->GetIdx(is_unicode, 3); // 获取第4个参数
//         // 获取其它参数
//         if (is_unicode)
//         {
//             const WCHAR* wstr;
//             args->Get(a, b, wstr, is_unicode);
//             return args->PushRet(a-b, a, b, wstr); // 函数有4个返回值
//         }
//         else
//         {
//             const ACHAR* astr;
//             args->Get(a, b, astr, is_unicode);
//             return args->PushRet(a-b, a, b, astr); // 函数有4个返回值
//         }
//         return 0; // 无返回值时返回0
//     }
//     
//     IFLua* lua = FNewLua(FNEW_INFO);
//     if (lua->Run(_FT("..\\sample\\lua.lua")))
//     {
//         // 获取全局变量
//         bool bool_vl = lua->GetBool(_FT("bool_vl"));
//         int int_vl = lua->GetInt(_FT("int_vl"));
//         float float_vl = lua->GetFloat(_FT("float_vl"));
//         FString str_vl = lua->GetString(_FT("str_vl"));
//     
//         {   // 手动且显式执行一个lua脚本中的函数
//             IFLuaFunc* func = lua->GetFunc(_FT("add"));
//             int vl, i1, i2;
//             const NCHAR* tstr = 0;
//             if (func && func->Run(4, 35, 85, _FT("加法")))
//                 func->GetRet(vl, i1, i2, tstr);
//             lua->FreeFunc(func);
//         }
//     
//         {   // 自动且安全地执行一个lua脚本中的函数
//             int vl, i1, i2;
//             const NCHAR* tstr = 0;
//             FLuaFunc func(lua, _FT("add"));
//             if (func(4, 654, 878, _FT("加法")))
//                 func.GetRet(vl, i1, i2, tstr);
//         }
//     
//         {   // 注册一个函数到lua脚本
//             if (lua->RegFunc(_FT("sub"), my_sub_func))
//             {
//                 int_vl = lua->GetInt(_FT("int_vl"));
//                 // 模拟脚本调用函数（注意lua脚本调用函数只支持ANSI串）
//                 if (lua->RunString(_FT("sub(120, 21, \"减法\", 0)")))
//                     int_vl = lua->GetInt(_FT("int_vl"));
//                 // 访问函数来调用（从代码调用函数是支持UINCODE的）
//                 int vl, i1, i2;
//                 const NCHAR* tstr = 0;
//                 FLuaFunc func(lua, _FT("sub"));
//                 if (func(4, 554, 5465, _FT("减法"), 1))
//                 {
//                     int_vl = lua->GetInt(_FT("int_vl"));
//                     func.GetRet(vl, i1, i2, tstr);
//                 }
//             }
//         }
//     }
//     FDel(lua);
//
//----------------------------------------------------------------
#pragma once


#include "Core/IFDoc_LuaFunc.h"


class IFLua : public IFMemObject
{
protected:
    explicit IFLua()
    {}

public:
    // 当前解释器是否有效
    virtual bool IsValid() = 0;
    // 加载lua文件并解析
    FINLINE bool Run (const NCHAR* file);
    virtual bool RunW(const WCHAR* file) = 0;
    virtual bool RunA(const ACHAR* file) = 0;
    // 加载lua语句并解析
    FINLINE bool RunString (const NCHAR* str);
    virtual bool RunStringW(const WCHAR* str) = 0;
    virtual bool RunStringA(const ACHAR* str) = 0;
    // 设置全局变量为无效值
    FINLINE void SetNil (const NCHAR* name);
    virtual void SetNilW(const WCHAR* name) = 0;
    virtual void SetNilA(const ACHAR* name) = 0;
    // 全局变量是否有效
    FINLINE bool IsNil (const NCHAR* name);
    virtual bool IsNilW(const WCHAR* name) = 0;
    virtual bool IsNilA(const ACHAR* name) = 0;
    // 设置与获取全局变量值（bool）
    FINLINE void SetBool (const NCHAR* name, bool vl);
    virtual void SetBoolW(const WCHAR* name, bool vl) = 0;
    virtual void SetBoolA(const ACHAR* name, bool vl) = 0;
    FINLINE bool GetBool (const NCHAR* name);
    virtual bool GetBoolW(const WCHAR* name) = 0;
    virtual bool GetBoolA(const ACHAR* name) = 0;
    // 设置与获取全局变量值（int）
    FINLINE void SetInt (const NCHAR* name, int vl);
    virtual void SetIntW(const WCHAR* name, int vl) = 0;
    virtual void SetIntA(const ACHAR* name, int vl) = 0;
    FINLINE int GetInt (const NCHAR* name);
    virtual int GetIntW(const WCHAR* name) = 0;
    virtual int GetIntA(const ACHAR* name) = 0;
    // 设置与获取全局变量值（float）
    FINLINE void SetFloat (const NCHAR* name, float vl);
    virtual void SetFloatW(const WCHAR* name, float vl) = 0;
    virtual void SetFloatA(const ACHAR* name, float vl) = 0;
    FINLINE float GetFloat (const NCHAR* name);
    virtual float GetFloatW(const WCHAR* name) = 0;
    virtual float GetFloatA(const ACHAR* name) = 0;
    // 设置与获取全局变量值（string）
    FINLINE void SetString (const NCHAR* name, const NCHAR* vl);
    virtual void SetStringW(const WCHAR* name, const WCHAR* vl) = 0;
    virtual void SetStringA(const ACHAR* name, const ACHAR* vl) = 0;
    FINLINE const NCHAR* GetString (const NCHAR* name);
    virtual const WCHAR* GetStringW(const WCHAR* name) = 0;
    virtual const ACHAR* GetStringA(const ACHAR* name) = 0;
    // 从lua脚本中获取并创建函数对象（结束以后需要调用FreeFunc）
    FINLINE IFLuaFunc* GetFunc (const NCHAR* name);
    virtual IFLuaFunc* GetFuncW(const WCHAR* name) = 0;
    virtual IFLuaFunc* GetFuncA(const ACHAR* name) = 0;
    // 注册一个本地函数并创建函数对象
    FINLINE bool RegFunc (const NCHAR* name, F_LUA_FUNC func);
    virtual bool RegFuncW(const WCHAR* name, F_LUA_FUNC func) = 0;
    virtual bool RegFuncA(const ACHAR* name, F_LUA_FUNC func) = 0;
    // 释放由 GetFunc 创建的函数对象
    virtual void FreeFunc(IFLuaFunc*& func) = 0;
};


class FLuaFunc
{
public:
    IFLuaFunc* func;
    FINLINE FLuaFunc(IFLua* l, const WCHAR* n)
        :func(0)
    {
        func = l->GetFuncW(n);
    }
    FINLINE FLuaFunc(IFLua* l, const ACHAR* n)
        :func(0)
    {
        func = l->GetFuncA(n);
    }
    FINLINE ~FLuaFunc()
    {
        if (func)
            func->GetLua()->FreeFunc(func);
    }

    // 执行函数（无参）
    bool operator()(size_t rt_count = 0)
    {
        if (!func)
            return false;
        return func->__Execute(rt_count, 0, 0);
    }
    // 执行函数（多参）
#define FLUA_FUNC_OP(n)\
    template < FLUA_TYPE##n >\
    FINLINE bool operator()(size_t rt_count, FLUA_ARGC##n)\
    {\
        if (!func)\
            return false;\
        IFLuaFunc::DT arg[n] = {FLUA_VAL##n};\
        return func->__Execute(rt_count, arg, n);\
    }
    FLUA_FUNC_OP(1)     //  1个参数的 operator() 函数
    FLUA_FUNC_OP(2)     //  2个参数的 operator() 函数
    FLUA_FUNC_OP(3)     //  3个参数的 operator() 函数
    FLUA_FUNC_OP(4)     //  4个参数的 operator() 函数
    FLUA_FUNC_OP(5)     //  5个参数的 operator() 函数
    FLUA_FUNC_OP(6)     //  6个参数的 operator() 函数
    FLUA_FUNC_OP(7)     //  7个参数的 operator() 函数
    FLUA_FUNC_OP(8)     //  8个参数的 operator() 函数
    FLUA_FUNC_OP(9)     //  9个参数的 operator() 函数
    FLUA_FUNC_OP(10)    // 10个参数的 operator() 函数
    FLUA_FUNC_OP(11)    // 11个参数的 operator() 函数
    FLUA_FUNC_OP(12)    // 12个参数的 operator() 函数

    // 获取函数返回值
#define FLUA_RET_OP(n)\
    template < FLUA_TYPE##n >\
    FINLINE bool GetRet(FLUA_ARGR##n)\
    {\
        if (!func)\
            return false;\
        IFLuaFunc::DT_RET arg[n] = {FLUA_VAL##n};\
        return func->__GetResult(arg, n);\
    }
    FLUA_RET_OP(1)  //  1个参数的 GetRet 函数
    FLUA_RET_OP(2)  //  2个参数的 GetRet 函数
    FLUA_RET_OP(3)  //  3个参数的 GetRet 函数
    FLUA_RET_OP(4)  //  4个参数的 GetRet 函数
    FLUA_RET_OP(5)  //  5个参数的 GetRet 函数
    FLUA_RET_OP(6)  //  6个参数的 GetRet 函数
    FLUA_RET_OP(7)  //  7个参数的 GetRet 函数
    FLUA_RET_OP(8)  //  8个参数的 GetRet 函数
    FLUA_RET_OP(9)  //  9个参数的 GetRet 函数
    FLUA_RET_OP(10) // 10个参数的 GetRet 函数
    FLUA_RET_OP(11) // 11个参数的 GetRet 函数
    FLUA_RET_OP(12) // 12个参数的 GetRet 函数
};

#include "Core/IFDoc_Lua_inl.h"

extern FAPI IFLua* FNewLua(FNEW_FUNC_API, DWORD init_libs = eLIL_ALL);